package opt.power.springdemo.user.service;

import opt.power.springdemo.exception.ResourceNotFoundException;
import opt.power.springdemo.user.mapper.UserMapper;
import opt.power.springdemo.user.mapper.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.stream.Stream;

/**
 * 这个只是个demo，user的存储直接使用map，并且默认添加了管理员账号
 * admin/123123
 * <p>
 * 类 UserService 中的方法都以 Flux 或 Mono 对象作为返回值，
 * 这也是 WebFlux 应用的特征。
 * 在方法 getById()中，如果找不到 ID 对应的 User 对象，
 * 会返回一个包含了 ResourceNotFoundException 异常通知的 Mono 对象。
 * 方法 getById()和 createOrUpdate()都可以接受 String 或 Flux 类型的参数。
 * Flux 类型的参数表示的是有多个对象需要处理。这里使用 doOnNext()来对其中的每个对象进行处理。
 *
 * @author xuliduo
 * @date 2017/11/16
 * @description class UserService
 */
@Service
public class UserService {

    UserMapper userMapper;

    @Autowired
    UserService(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    /**
     * 返回所有的用户对象
     *
     * @return users
     */
    public Flux<User> list() {
        return Flux.fromIterable(userMapper.getAll());
    }

    /**
     * 返回对象；
     * 如果找不到 ID 对应的 User 对象，
     * 会返回一个包含了空的Mono对象。
     *
     * @param ids ids
     * @return users
     */
    Flux<User> getById(final Flux<Long> ids) {
        return ids.flatMap(id -> Mono.justOrEmpty(userMapper.findById(id)));
    }

    /**
     * 返回对象；
     * 如果找不到 ID 对应的 User 对象，
     * 会返回一个包含ResourceNotFoundException 异常通知的 Mono 对象
     *
     * @param id id
     * @return user or ResourceNotFoundException
     */
    public Mono<User> getById(final Long id) {
        return Mono.justOrEmpty(userMapper.findById(id))
                .switchIfEmpty(Mono.error(new ResourceNotFoundException()));
    }

    /**
     * 更新或者创建多个对象
     *
     * @param users users
     * @return users
     */
    public Flux<User> createOrUpdate(final Flux<User> users) {
        return users.doOnNext(user -> {
            if (user.getId() > 0) {
                userMapper.update(user);
            } else {
                userMapper.insert(user);
            }
        });
    }

    /**
     * 更新或者创建多个对象
     *
     * @param users users
     * @return users
     */
    public Flux<User> createOrUpdate(final List<User> users) {
        users.forEach(user -> {
            if (user.getId() > 0) {
                userMapper.update(user);
            } else {
                userMapper.insert(user);
            }
        });
        return Flux.fromIterable(users);
    }

    /**
     * 更新或者创建对象
     *
     * @param user user
     * @return user
     */
    public Mono<User> createOrUpdate(final User user) {
        if (user.getId() > 0) {
            userMapper.update(user);
        } else {
            userMapper.insert(user);
        }
        return Mono.just(user);
    }

    /**
     * 删除对象
     *
     * @param id user id
     * @return mono -> null
     */
    public Mono<User> delete(final Long id) {
        userMapper.delete(id);
        return Mono.empty();
    }
}
